package com.middleware.mvc.handleMapping;


import com.middleware.mvc.annotations.RequestMapping;
import com.middleware.mvc.context.WebApplicationContext;
import com.middleware.mvc.handler.InvocationHandler;
import com.middleware.mvc.loaders.WebXmlServletLoader;
import com.middleware.mvc.servlet.DispatcherServlet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.beans.Introspector;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class HandlerMapping {

    Logger log = LoggerFactory.getLogger(HandlerMapping.class);

    private static Map<String, InvocationHandler> handlerMap;

    private static final String servletName = "DispatcherServlet";
    public void init(List<Class<?>> classList, WebApplicationContext webApplicationContext){
        String basePath = getBasePath();
        // 初始化一个 Map 集合，用于存放映射关系
        HashMap<String, InvocationHandler> HandlerHashMap = new HashMap<>();
        // 遍历 Controller 集合（也就是所有带@Controller注解的类）
        for (Class<?> aClass : classList) {
            //获取类上@RequestMapping注解的值
            String classReqPath = getAnnotationValue(aClass, RequestMapping.class);
            System.out.println("类的请求路径:" + classReqPath);

            // 获取这个 class 类中的所有方法
            Method[] methods = aClass.getDeclaredMethods();
            System.out.println("类中方法数量为：" + methods.length);

            // 开始遍历这个类中的所有方法
            for (Method method : methods) {
                // 判断每个方法上是否带有@RequestMapping注解
                boolean flag = method.isAnnotationPresent(RequestMapping.class);
                // 如果当前方法上带有这个注解
                if (flag){
                    // 获取方法上@RequestMapping注解的值
                    String methodReqPath = getAnnotationValue(method, RequestMapping.class);
                    // 判断得到的值是否为空，不为空则获取对应的值
                    String reqPath = methodReqPath == null ||
                            methodReqPath.isEmpty() ? "" : methodReqPath;
                    System.out.println("方法上的请求路径:" + reqPath);
                    // 将得到的值封装成 InvocationHandler 对象
                    try {
                        // 放入一个当前类的实例对象，用于执行后面的类方法
                        InvocationHandler invocationHandler = new
                                InvocationHandler(webApplicationContext.getBean(aClass), method);
                        // 使用 类的请求路径 + 方法的请求路径 作为Key
                        HandlerHashMap.put( basePath + classReqPath + reqPath,
                                invocationHandler);
                    }catch (Exception e){
                        log.error("获取bean实例对象失败", e);
                    }
                }
            }
        }
        // 将存放映射关系的Map集合返回
        handlerMap = HandlerHashMap;
    }

    public InvocationHandler getHandler(String reqPath){
        return handlerMap.get(reqPath);
    }

    private String getAnnotationValue(Class<?> aClass, Class<RequestMapping> requestMappingClass) {
        RequestMapping annotation = aClass.getAnnotation(requestMappingClass);
        return annotation == null ? null : annotation.value();
    }

    private String getAnnotationValue(Method method, Class<RequestMapping> requestMappingClass) {
        RequestMapping annotation = method.getAnnotation(requestMappingClass);
        return annotation == null ? null : annotation.value();
    }

    private String getBasePath() {
        String value = WebXmlServletLoader.getValue(servletName);
        //获取到value 中的第二个‘/’的位置
        int index = value.indexOf("/", 1);

        return value.substring(0, index);
    }
}
